/*
 * Copyright (c) 2010, German Buela
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * The name of German Buela may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY GERMAN BUELA "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL GERMAN BUELA BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.gbuela.winco.view

import org.eclipse.swt.custom._
import com.gbuela.swt._
import com.gbuela.winco.model._
import com.gbuela.winco.business._

class TrackCheck(val check: SwtCheckbox, val track: Track) {
  def isChecked = check.isChecked
}

class CustomPlaylistView(override val tf:SwincoTabFolder, override val alb:AbstractAlbum, override val launcher:PlayerLauncher)
extends AlbumView(tf, alb, launcher) {
    override protected def albumControls(): SwtComp =  fill (
       image("./del.gif").click("./delpush.gif").at(33,0).onClick(tf.removeTracksFromCustomPlaylist(checkedTracks)).withTooltip("Remove selected tracks")
    )
}
class AlbumView(val tf:SwincoTabFolder, val alb:AbstractAlbum, val launcher:PlayerLauncher) extends TabView with SwtHelper {
  val tabText = alb.title
  var album: AbstractAlbum = alb
  var checks: List[TrackCheck] = initChecks
  val data = alb
  
  private def initChecks =  album.tracks map { t: Track => new TrackCheck(checkbox(" "), t) }
  private lazy val isLandscape: Boolean = {
    import javax.swing.ImageIcon
    val ii = new ImageIcon(album.imageInfo.mainFilename)
    ii.getIconWidth > ii.getIconHeight
  }
  private lazy val scaleWidth = if(!album.imageInfo.isBigImage || !isLandscape) 200 else 400 
  private lazy val scaleHeight =  if(!album.imageInfo.isBigImage || isLandscape) 200 else 400 
  
  init
  
  def init:Unit = {
      val ct = checkedTracks // save currently checked tracks (for some reason  checked flag  gets lost during init)
      checks = initChecks
      
	  addContent { 
	    horizontal(
		    vertical(
		      label((album.year getOrElse "").toString, 9) ,
		      label(album.title, 14) ,
		      label(album.artistName, 11),
		      vertical.withRowData(scaleWidth + 10, scaleHeight + 10) (
		         image(album.imageInfo.mainFilename, album.imageInfo.fallbackFilename).hover(album.imageInfo.altFilename getOrElse null).at(5,5).scaleTo(scaleWidth, scaleHeight). onClick( launcher.launchPlaylist(album.tracks, album.location)).withTooltip("Click to play album")
		      ),
			  fill.withRowData(200,35) (
				  image("./launch.gif").click("./launchpush.gif").at(0,0).onClick(launcher.launchPlaylist(checkedTracks,album.location)).withTooltip("Play selected tracks"),
	 		      albumControls,
	 		      checkbox("All")  onClick selectAll
		        )
		    ),
		    vertical(
		      horizontal(
		        image("./up_s.gif").click("./uppush_s.gif").withTooltip("move selected tracks up").onClick(shiftTracks(shiftUp)),
		        image("./down_s.gif").click("./downpush_s.gif").withTooltip("move selected tracks down").onClick(shiftTracks(shiftDn))          
		      ),
		      vertical( trackLabels )  
            )
	    )
	  }
   
     // restore check data
     (checks filter (ct contains _.track)) foreach (_.check.setChecked(true))
  }
  
  protected def albumControls(): SwtComp =  fill (
     image("./add.gif").click("./addpush.gif").at(33,0).onClick(tf.addTracksToCustomPlaylist(checkedTracks, alb.location)).withTooltip("Add selected tracks to custom playlist"),
     image("./reload.gif").at(66,0).onClick(reload).withTooltip("Reload tracks")
  )
  
  private def reload: Unit = doWithRefresh {
    val album = alb.asInstanceOf[Album]
    album.reloadSwincoPlaylist
  }
  
  private def shiftTracks(shifter: (Array[TrackCheck], TrackCheck => Boolean) => Array[TrackCheck]) = doWithRefresh {
    checks = shifter(checks.toArray, { tc: TrackCheck => tc.isChecked }).toList
    album setTracks checks.map(_.track)
    album writeSwincoPlaylist album.tracks
  }
  
  private def trackLabels():List[SwtComp] = checks map { tc: TrackCheck =>
      horizontal (tc.check, label(tc.track.title, 10, { launcher.launchPlaylist(tc.track :: Nil, alb.location)}) ) 
  }
  
  protected def checkedTracks: List[Track] = (checks filter (_.isChecked)) map (_.track)
  private def selectAll(checked: Boolean) =  for(chk <- checks) chk.check.setChecked(checked)
  
  def setAlbum(alb: AbstractAlbum) = {
    album = alb
    init
  }
  
	def shiftUp[T](a: Array[T], p: T => Boolean) = {
	  val s = arrayCopy(a)
	  for (i <- 0 until s.length - 1; if !p(s(i)) && p(s(i+1))) {
	    val tmp = s(i); s(i) = s(i+1); s(i+1) = tmp // swap
	  }
	  s
	}
 	def shiftDn[T](a: Array[T], p: T => Boolean) = {
	  val s = arrayCopy(a)
	  for (i <- s.length - 1 to 1 by -1; if !p(s(i)) && p(s(i-1))) {
	    val tmp = s(i); s(i) = s(i-1); s(i-1) = tmp // swap
	  }
	  s
	}
 
   private def arrayCopy[T](ori: Array[T]): Array[T] = {
	  val cpy = new Array[T](ori.length)
      ori.copyToArray(cpy, 0)
      cpy
   }
 }